#!/usr/bin/env bash

# This file defines anonbot, an irc bot used on irc.sdf.org.

# Copyright (C) 2015-2021 mlaine@sdfeu.org

# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:

# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.

# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

#-----------------------------------------------------------------------

host='irc.sdf.org'
port=6667
user='bot'
nick='anonbot'
real='Anonradio Bot'
chan='#anonradio'

stat='http://anonradio.net:8000/status-json.xsl'
sched='https://anonradio.net/schedule/'

function init {
    exec 3<&-
    kill "$pid" 2>'/dev/null'
    exec 3<>"/dev/tcp/$host/$port" || return 1
    printf 'USER %s 0 * :%s\n' "$user" "$real" >&3
    printf 'NICK %s\n' "$nick" >&3
    update &
    pid="$!"
}

function status {
    raw="$(curl --connect-timeout 5 -fs "$stat")"
    for str in 'server_name' 'title' 'listeners'; do
        declare -g $str="$(awk -F "$str\":" '
        {
            split($2,s,",\"")
            gsub(/"/,"",s[1])
            gsub(/ *$/,"",s[1])
            print s[1]
        }
        ' <<< "$raw")"
    done
    if [[ -z "$server_name" || -z "$listeners" ]]; then
        return 1
    fi
}

function schedule {
    raw="$(curl --connect-timeout 5 -Lkfs "$sched")"
    if [[ -z "$raw" ]]; then
        send 'Could not fetch the schedule.'
        return
    fi
    if [[ "$1" == 'cur' ]]; then
        host="$(printf "$raw" | awk 'NR==5{print $3}')"
        show="$(printf "$raw" | awk 'NR==5{$1=$2=$3="";print}' | awk '{$1=$1};1')"
        send "Current show, hosted by $host: $show"
        return
    elif [[ "$1" == 'next' ]]; then
        time="$(printf "$raw" | awk 'NR==6{print $2}')"
        host="$(printf "$raw" | awk 'NR==6{print $3}')"
        show="$(printf "$raw" | awk 'NR==6{$1=$2=$3="";print}' | awk '{$1=$1};1')"
        send "Next show, hosted by $host at $time: $show"
    else
        send 'Anonradio schedule for the next 10 shows:'
        readarray -t foo <<< "$(printf "$raw" | awk 'NR>5&&NR<16')"
        for str in "${foo[@]}"; do
            send "$str"
        done
    fi
    send "The time is now $(date -u '+%R (all times in %Z)')."
}

function send {
    if [[ "${FUNCNAME[1]}" = 'push' ]]; then
        colour="\x0303"
    else
        colour="\x0307"
    fi
    printf 'PRIVMSG %b\n' "$chan :$colour$1\x03" >&3
}

function push {
    send "$server_name ${title:+: $title }($listeners listeners)"
}

function update {
    sleep 10
    current=''
    while true; do
        if status; then
            if [[ "$title" != "$current" ]]; then
                current="$title"
                push && sleep 120
            fi
        else
            sleep 60 && continue
        fi
        sleep 20
    done
}

function priv {
    case "$1" in
        'np')
            if status; then
                push
            else
                send 'No program at the moment.'
            fi ;;
        'help')
            send "Type 'np' for now playing, 'current' for the current show, 'next' for the next show, 'schedule' for the next ten shows and 'source' for my source." ;;
        'source')
            send 'You can view my source at https://notabug.org/mlaine/anonbot.' ;;
        'current')
            schedule 'cur' ;;
        'next')
            schedule 'next' ;;
        'schedule')
            schedule ;;
    esac
}

function main {
    init
    while true; do
        if IFS=$' \t\r' read -ru3 -a data -t 300; then
            if [[ "${data[0]}" = 'PING' ]]; then
                printf 'PONG %s\n' "${data[1]}" >&3
            elif [[ "${data[1]}" = '001' ]]; then
                printf 'JOIN %s\n' "$chan" >&3
            elif [[ "${data[1]}${data[3]}" = "PRIVMSG:$nick:" ]]; then
                priv "${data[4],,}" 
            fi
        else
            sleep 300
            init
        fi
    done
}

main

